﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml.Serialization;

namespace Tunynet.MobileSMS
{
    /// <summary>
    /// 序列化发送请求
    /// </summary>
    public class XmlResponse
    {

        /// <summary>
        /// 构造函数
        /// </summary>
        static XmlResponse()
        {
            if (CookieContainer == null)
            {
                CookieContainer = new CookieContainer();
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="urlAPI">请求地址</param>
        public XmlResponse(string urlAPI = "http://121.199.48.186:1210/Services/MsgSend.asmx/")
        {
            url = urlAPI;
        }

        /// <summary>
        /// 容器
        /// </summary>
        public static CookieContainer CookieContainer;

        /// <summary>
        /// 缓存
        /// </summary>
        private static Dictionary<int, XmlSerializer> serializer_dict = new Dictionary<int, XmlSerializer>();

        private string url;
        /// <summary>
        /// 请求地址
        /// </summary>
        internal string Url
        {
            get { return url; }
            set { url = value; }
        }

        /// <summary>
        /// 发送请求
        /// </summary>
        /// <typeparam name="T">请求返回的类型</typeparam>
        /// <param name="method_name">远程方法</param>
        /// <param name="parameters">方法参数</param>
        /// <returns></returns>
        public T GetResponse<T>(string method_name, params YunXinParam[] parameters)
        {
            YunXinParam[] signed = parameters;
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < signed.Length; i++)
            {
                if (i > 0)
                    builder.Append("&");
                builder.Append(signed[i].ToEncodedString());
            }
            Url = Url + method_name;
            byte[] response_bytes = GetResponseBytes(Url, builder.ToString());
            XmlSerializer response_serializer = GetSerializer(typeof(T));
            try
            {
                T response = (T)response_serializer.Deserialize(new MemoryStream(response_bytes));
                return response;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        #region 私有方法

        /// <summary>
        /// 发送请求
        /// </summary>
        /// <param name="apiUrl">地址</param>
        /// <param name="postData">参数</param>
        /// <returns></returns>
        private byte[] GetResponseBytes(string apiUrl, string postData)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(apiUrl);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = postData.Length;
            request.Timeout = 20000;
            if (CookieContainer == null)
                CookieContainer = new CookieContainer();
            request.CookieContainer = CookieContainer;
            HttpWebResponse response = null;
            try
            {
                StreamWriter swRequestWriter = new StreamWriter(request.GetRequestStream());
                swRequestWriter.Write(postData);
                if (swRequestWriter != null)
                    swRequestWriter.Close();
                response = (HttpWebResponse)request.GetResponse();
                using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
                {
                    return Encoding.UTF8.GetBytes(reader.ReadToEnd());
                }
            }
            finally
            {
                if (response != null)
                    response.Close();
            }
        }


        /// <summary>
        /// 序列化对象
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private XmlSerializer GetSerializer(Type t)
        {
            int type_hash = t.GetHashCode();
            if (!serializer_dict.ContainsKey(type_hash))
                serializer_dict.Add(type_hash, new XmlSerializer(t));
            return serializer_dict[type_hash];
        }

        #endregion
    }
}
